package ph.edu.upd.eee.upcatarchivesearch;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Created by smartwire on 10/2/2014.
 */
public class UpdateProgressDialogFragment extends DialogFragment {
    private static final int DL_NONE = 0x0;
    private static final int DL_INPROGRESS = 0x1;
    private static final int DL_DONE = 0x2;

    private int finishDownload = DL_NONE;
    private ProgressBar pBarUpdate;
    private TextView txtUpdate;

    private DownloadArchive dlTask;

    public static UpdateProgressDialogFragment newInstance() {
        return new UpdateProgressDialogFragment();
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder alertDiagBuilder = new AlertDialog.Builder(getActivity());
        View v = getActivity().getLayoutInflater().inflate(R.layout.dialog_update, null);

        pBarUpdate = (ProgressBar) v.findViewById(R.id.pbar_updatedialog_update);
        txtUpdate = (TextView) v.findViewById(R.id.txt_dialogupdate_update);

        alertDiagBuilder
                .setView(v)
                .setTitle(R.string.txt_update)
                .setPositiveButton(R.string.btn_updatestart, null) // Has another listener
                .setNegativeButton(R.string.btn_updatecancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        UpdateProgressDialogFragment.this.getDialog().cancel();
                    }
                });

        return alertDiagBuilder.create();
    }

    @Override
    public void onStart() {
        super.onStart();

        AlertDialog d = (AlertDialog) getDialog();
        d.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String connectionType;

                dlTask = new DownloadArchive();
                if(finishDownload == DL_NONE) {
                        connectionType = Utility.getConnectionType(getActivity().getApplicationContext());

                        if(connectionType.equals(Utility.NETWORK_DISCONNECTED)) {
                            Toast.makeText(getActivity().getApplicationContext(), R.string.toast_nonetwork, Toast.LENGTH_LONG).show();
                        }
                        else if(connectionType.equals(Utility.NETWORK_MOBILE_FAST)) {
                            new AlertDialog.Builder(getActivity())
                            .setPositiveButton(R.string.diag_positive, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    dlTask.execute();
                                }
                            })
                            .setNegativeButton(R.string.diag_negative, null)
                            .setMessage(R.string.diag_mobilenet)
                            .show();
                        }
                        else {
                            dlTask.execute();
                        }
                }
            }
        });

        d.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                switch(finishDownload) {
                    case DL_INPROGRESS:
                        dlTask.cancel(false);

                        finishDownload = DL_NONE;
                    case DL_NONE:
                    case DL_DONE:
                    default:
                        dismiss();
                }
            }
        });
    }

    private class DownloadArchive extends AsyncTask <Void, Integer, Void> {
        private AlertDialog d;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            d = (AlertDialog) getDialog();
            d.getButton(DialogInterface.BUTTON_POSITIVE).setVisibility(View.INVISIBLE);
            d.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.VISIBLE);

            txtUpdate.setText(R.string.txt_update_init);
            pBarUpdate.setIndeterminate(true);
        }

        @Override
        protected Void doInBackground(Void... voids) {
            int totalSize, downloadedSize;
            int count;
            byte data[];
            String savePath;

            URL downloadURL;
            HttpURLConnection httpURLCxn = null;
            InputStream urlFileIn = null;
            FileOutputStream fileOut = null;
            File outFile;
            ZipInputStream zipIn = null;
            ZipEntry zipEnt;

            finishDownload = DL_INPROGRESS;

            try {
                // Download file from internet
                savePath = getActivity().getExternalFilesDir(null) + "";
                downloadURL = new URL(Utility.ARCHIVE_URL);
                httpURLCxn = (HttpURLConnection) downloadURL.openConnection();

                Log.d("app", "Connected to update server with response " + httpURLCxn.getResponseCode());

                totalSize = httpURLCxn.getContentLength();
                urlFileIn = httpURLCxn.getInputStream();
                fileOut = new FileOutputStream(savePath + "/upcatfinder.zip");
                Log.d("app", "Saving to " + savePath + "/upcatfinder.zip");

                // Check if cancelled
                if(isCancelled()) {
                    throw new Exception("Download cancelled.");
                }

                downloadedSize = 0;
                data = new byte[4096];
                while((count = urlFileIn.read(data)) != -1) {
                    downloadedSize += count;

                    // Check if cancelled
                    if(isCancelled()) {
                        throw new Exception("Download cancelled.");
                    }

                    if(totalSize > 0) {
                        publishProgress(totalSize, downloadedSize, 0);
                    }

                    fileOut.write(data, 0, count);
                }

                // Flag progress bar as decompressing
                publishProgress(totalSize, downloadedSize, 1);

                // Decompress files
                zipIn = new ZipInputStream(new FileInputStream(new File(savePath + "/upcatfinder.zip")));
                while((zipEnt = zipIn.getNextEntry()) != null) {
                    outFile = new File(savePath, zipEnt.getName());

                    outFile.getParentFile().mkdirs();

                    if(!zipEnt.isDirectory()) {
                        fileOut = new FileOutputStream(outFile);

                        data = new byte[4096];
                        while((count = zipIn.read(data)) > 0) {
                            fileOut.write(data, 0, count);
                        }

                        fileOut.close();
                        fileOut = null;
                    }
                }

                // Delete zip file
            }
            catch(Exception e) {
                Log.d("app", "Error in updating: " + e.getMessage());
                e.printStackTrace();
                //Toast.makeText(getActivity().getApplicationContext(), "Error in updating: " + e.getMessage(), Toast.LENGTH_SHORT).show();

                finishDownload = DL_NONE;
            }
            finally {
                try {
                    if(urlFileIn != null) {
                        urlFileIn.close();
                    }

                    if(fileOut != null) {
                        fileOut.close();
                    }

                    if(zipIn != null) {
                        zipIn.close();
                    }

                    if(httpURLCxn != null) {
                        httpURLCxn.disconnect();
                    }

                    outFile = new File(getActivity().getExternalFilesDir(null) + "/upcatfinder.zip");
                    if(outFile.exists()) {
                        outFile.delete();
                    }
                }
                catch(Exception ea) {
                    // Do nothing...
                }
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            super.onProgressUpdate(progress);

            switch(progress[2]) {
                case 0:
                    int percent = (int) (progress[1] / (double) progress[0] * 100);

                    pBarUpdate.setIndeterminate(false);
                    pBarUpdate.setMax(100);
                    pBarUpdate.setProgress(percent);

                    txtUpdate.setText("Downloaded " + Utility.bytesToSI(progress[1]) + " of " + Utility.bytesToSI(progress[0]) + " (" + percent + "%)...");

                    break;

                case 1:
                    pBarUpdate.setIndeterminate(true);
                    d.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.INVISIBLE);
                    txtUpdate.setText(R.string.txt_update_decompress);
            }
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            pBarUpdate.setIndeterminate(false);
            pBarUpdate.setProgress(100);
            txtUpdate.setText(R.string.txt_update_finishall);
            d.getButton(DialogInterface.BUTTON_NEGATIVE).setText(R.string.btn_updateexit);
            d.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.VISIBLE);

            finishDownload = DL_DONE;
            Log.d("app", "Update completed successfully!");
        }

        @Override
        protected void onCancelled(Void aVoid) {
            // Do nothing

            Log.d("app", "Update cancelled successfully!");
        }
    }
}
